<?php
/**
 *
 * RedisHashMapKey
 *
 * RedisHashMapModel.class.php
 * Created by IntelliJ IDEA.
 *
 * @author: hjh <hjh@jf.com>
 *
 * Date: 2017/10/30
 * Time: 15:57
 */

namespace Tools;

use Common\Bridge;

class RedisHashMapModel
{
    private $prefixKey;
    private static $_instance = [];

    private $redisRead = null;
    private $redisWrite = null;

    private $dbr;
    private $dbw;
    private $dbIndex;

    public function __construct($prefixKey, $dbIndex, $dbr = Bridge::REDIS_OTHER_R, $dbw = Bridge::REDIS_OTHER_W)
    {
        $this->prefixKey = $prefixKey;
        $this->dbIndex = $dbIndex;
        $this->dbr = $dbr;
        $this->dbw = $dbw;
    }

    /**
     * 获取单实例变量
     *
     * @param string $prefixKey 参考RedisDBConstant
     * @param int    $dbIndex   参看RedisDBConstant
     * @param int    $dbr
     * @param int    $dbw
     * @return mixed|\Tools\RedisHashMapModel
     */
    public static function instance($prefixKey, $dbIndex, $dbr = Bridge::REDIS_OTHER_R, $dbw = Bridge::REDIS_OTHER_W)
    {
        if (isset(self::$_instance[$prefixKey])) {
            return self::$_instance[$prefixKey];
        }
        $class = get_called_class();
        $i = new $class($prefixKey, $dbIndex, $dbr, $dbw);

        assert(!empty($i));

        self::$_instance[$prefixKey] = $i;

        return $i;
    }

    private function getReadRedis()
    {
        if ($this->redisRead === null) {
            $this->redisRead = Bridge::redis($this->dbr, $this->dbIndex);
        }
        return $this->redisRead;
    }

    private function getWriteRedis()
    {
        if ($this->redisWrite === null) {
            $this->redisWrite = Bridge::redis($this->dbw, $this->dbIndex);
        }
        return $this->redisWrite;
    }

    /**
     * 根据ID列表获取 Int 数据
     *
     * @param $ids
     * @param $field
     * @return array|bool 成功的情况下[ 1 => 100|FALSE ... ]， 当返回的值为FALSE时，表明需要重置一Redis缓存的数据
     */
    public function getIntValue($ids, $field)
    {
        $idsArray = is_array($ids) ? $ids : [$ids];

        $redis = $this->getReadRedis();
        $redis->multi(\Redis::PIPELINE);

        $idMap = [];
        foreach ($idsArray as $id) {
            $idMap[] = $id;
            $key = $this->prefixKey . $id;
            $redis->hGet($key, $field);
        }
        $data = $redis->exec();
        if (empty($data)) {
            debug_log('getInCache Failed, prefixKey' . $this->prefixKey . ', ids:' . json_encode($ids) . ', filed: ' . $field, JF_LOG_WARNING);
            return false;
        }
        $ret = array_combine($idMap, (array)$data);
        debug_log('getInCache Failed, prefixKey' . $this->prefixKey . ', ids:' . json_encode($ids) . ', filed: ' . $field);
        return is_array($ids) ? $ret : current($ret);
    }

    /**
     *  设置IntValue
     *
     * @param $id
     * @param $field
     * @param $add
     * @param $oldValue
     * @return int
     */
    public function incIntValue($id, $field, $add, $oldValue)
    {
        $redis = $this->getWriteRedis();
        $key = $this->prefixKey . $id;

        $ret = $redis->hIncrBy($key, $field, $add);
        if ($ret == $add) {
            $ret = $redis->hIncrBy($key, $field, $oldValue);
        }
        debug_log('setInCache , prefixKey' . $this->prefixKey . ', id:' . $id . ', filed: ' . $field. ', add: ' . $add. ', oldValue: ' . $oldValue);
        return $ret;
    }

    /**
     *
     * 获取Id对应的所有的字段
     *
     * @param $ids
     * @return array|mixed   返回的数据 [ id => ['field'=> $value, ... ] ...]  当$value值为FALSE的时候，表示需要将对应的ID的数据充值
     */
    public function getAllFieldValue($ids)
    {
        $redis = $this->getReadRedis();
        $idArray = is_array($ids) ? $ids : [$ids];

        $redis->multi(\Redis::PIPELINE);
        $idMap = [];
        foreach ($idArray as $id) {
            $idMap[] = $id;
            $redis->hGetAll($this->prefixKey . $id);
        }
        $data = $redis->exec();
        $ret = array_combine($idMap, (array)$data);
        return is_array($ids) ? $ret : current($ret);
    }
}
